﻿//
// Created by WJ on 2025/9/17.
//

#ifndef MODBUSTCP_CLIENT_H
#define MODBUSTCP_CLIENT_H

#include <functional>
#include <libmodbus/modbus.h>
#include <thread>
#include <atomic>
#include <iostream>
#include <ostream>
#include <mutex>

struct MonitorTask
{
    int addr;
    std::thread monitorThread;
    std::atomic<bool> isMonitoring;
    std::thread::id threadId;
};


class ModbusTcpClient
{
public:
    // 构造函数
    ModbusTcpClient();

    // 析构函数
    ~ModbusTcpClient();

    // 连接到服务器
    bool connect();

    // 断开与服务器的连接
    void disconnect();

    // 读取某个寄存器地址的值
    bool read(int addr, int nb, uint16_t* dest);

    // 写入某个值到寄存器地址
    bool write(int reg_addr, const uint16_t value);

    // 写入多个值到寄存器地址
    bool write(int addr, int nb, const uint16_t* data);

    // 检测到上升沿的函数
    static void detectedRisingFunction()
    {
        std::cout << "检测到上升沿" << std::endl;
    }

    // 监听某个寄存器地址
    template <typename ConditionFunc, typename CallbackFunc>
    void startMonitor(MonitorTask& task, int addr, std::chrono::milliseconds samplingInterval, ConditionFunc&& condition, CallbackFunc&& callback)
    {
        // 检查是否已经在监听，防止重复启动
        if (task.isMonitoring.load())
        {
            std::cout << "该任务已在监听中，无法重复启动。" << std::endl;
            return;
        }

        // 设置任务地址并启动监控
        task.addr = addr;
        task.isMonitoring = true;

        task.monitorThread = std::thread([this, &task, samplingInterval, condition = std::forward<ConditionFunc>(condition), callback = std::forward<CallbackFunc>(callback)]() mutable
        {
            // 记录线程ID
            task.threadId = std::this_thread::get_id();
            std::cout << "监控线程已启动，ID：" << task.threadId << std::endl;

            uint16_t prevValue = 0;
            uint16_t currentValue = 0;

            // 初始读取，如果失败则退出
            if (!this->read(task.addr, 1, &prevValue))
            {
                std::cerr << "初始读取寄存器失败，地址：" << task.addr << "。监控线程将退出。" << std::endl;
                task.isMonitoring = false;
                return;
            }
            currentValue = prevValue;

            while (task.isMonitoring.load())
            {
                if (this->read(task.addr, 1, &currentValue))
                {
                    if (condition(prevValue, currentValue))
                    {
                        callback(prevValue, currentValue);
                    }
                    prevValue = currentValue;
                }
                else
                {
                    std::cerr << "监听线程读取寄存器失败，地址：" << task.addr << std::endl;
                    task.isMonitoring = false;
                }
                std::this_thread::sleep_for(samplingInterval);
            }
            std::cout << "监控线程已退出。" << std::endl;
        });
    }

    // 停止监听
    void stopMonitor(MonitorTask& task);

private:
    modbus_t* ctx;
    std::mutex ctx_mutex;

    MonitorTask risingEdgeTask;
};


#endif //MODBUSTCP_CLIENT_H
